// RedJey Graphics User Interface Library for J2ME Platform.
// Copyright (C) 2008 Yevgen Krapiva
//
// This library is free software; you can redistribute
// it and/or modify it under the terms of the
// GNU Lesser General Public License as published
// by the Free Software Foundation; either version 3.0
// of the License, or any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this library; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//

package com.incrediblesoft.redjey;

/**
 * @author Yevgen Krapiva<br>
 *         Homepage: http://code.google.com/p/redjey/<br>
 *         Feedback: ykrapiva@gmail.com<br>
 *         Copyright (C) 2008 Yevgen Krapiva<br>
 */

import com.incrediblesoft.redjey.event.MouseEvent;

import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import java.util.Hashtable;

public class Menu extends MenuItem
{
    public static final int LEFT_PLACEMENT = 1;
    public static final int RIGHT_PLACEMENT = 2;
    public static final int ABOVE_PLACEMENT = 4;
    public static final int BELOW_PLACEMENT = 8;

    protected PopupMenu popupMenu;
    protected boolean isOpened;
    protected int popupOrientation = ABOVE_PLACEMENT;
    protected CustomImage arrowImage;

    /**
     * Constructs menu
     * @param title Menu title
     */
    public Menu(String title)
    {
        this(title, null, null);
    }

    /**
     * Constructs menu with a given title and image
     * @param title Menu title
     * @param image Menu icon image
     */
    public Menu(String title, CustomImage image)
    {
        this(title, image, null);
    }

    /**
     * Constructs menu with a given title and image
     * @param title Menu title
     * @param image Menu image
     * @param styleClassName Menu style class name
     */
    public Menu(String title, CustomImage image, String styleClassName)
    {
        super(title, image, styleClassName);
        popupMenu = new PopupMenu();
        popupMenu.parentMenu = this;
        popupMenu.setFocusCycled(true);
    }

    public String getName()
    {
        return "Menu";
    }

    protected Dimension calcPreferredSize(int paddingHorizontal, int paddingVertical, CustomFont font, Hashtable attributes)
    {
        Dimension dim = super.calcPreferredSize(paddingHorizontal, paddingVertical, font, attributes);
        dim.width += arrowImage != null ? arrowImage.getWidth() + 5 : 0;
        dim.height = Math.max(dim.height, arrowImage != null ? arrowImage.getHeight(): 0);

        return dim;
    }

    protected void calcContentSize()
    {
        super.calcContentSize();
        contentSize.width += arrowImage != null ? arrowImage.getWidth() : 0;
        contentSize.height = Math.max(contentSize.height, arrowImage != null ? arrowImage.getHeight() : 0);
    }

    /**
     * Returns PopupMenu associated with this menu
     * @return PopupMenu
     */
    public PopupMenu getPopupMenu()
    {
        return popupMenu;
    }

    /**
     * Returns the number of menu items menu items in this menu
     * @return Menu item count
     */
    public int getItemCount()
    {
        return popupMenu.getComponentCount();
    }

    /**
     * Returns menu item at specified index
     * @param index Index
     * @return Menu item
     */
    public MenuItem getItem(int index)
    {
        return (MenuItem) popupMenu.getComponent(index);
    }

    /**
     * Adds menu item to this menu container
     * @param mi Menu item to add
     * @return Menu item that was added
     */
    public MenuItem add(MenuItem mi)
    {
        popupMenu.add(mi);
        return mi;
    }

    /**
     * Creates and adds menu item with specified label
     * @param label Menu item label
     * @return A newly created menu item
     */
    public MenuItem add(String label)
    {
        return add(new MenuItem(label));
    }

    /**
     * Removes menu item at specified index
     * @param index Menu item index
     */
    public void remove(int index)
    {
	    popupMenu.remove(index);
    }

    /**
     * Removes specified menu item from this menu container
     * @param item Menu item to remove
     */
    public void remove(MenuItem item)
    {
        int index = popupMenu.indexOf(item);
        if (index != -1)
            remove(index);
    }

    /**
     * Removes all menu items from this container
     */
    public void removeAll()
    {
	    int nitems = getItemCount();
	    for (int i = nitems-1 ; i >= 0 ; i--)
	        remove(i);
    }

    /**
     * Returns menu item index
     * @param item Menu item
     * @return Index
     */
    public int indexOf(MenuItem item)
    {
        return popupMenu.indexOf(item);
    }

    public void processMouseEvent(MouseEvent event)
    {
        switch(event.getID())
        {
            case MouseEvent.MOUSE_CLICKED:
                if (!isOpened) open();
                else
                {
                    close();
                    setState(NORMAL);
                }
                break;

            /*case MouseEvent.MOUSE_ENTERED:
                super.processMouseEvent(event);
                //if (parentMenu != null && !isOpened) open();
                break;*/

            default:
                super.processMouseEvent(event);
        }
    }

    /**
     * Opens popup menu associated with this menu
     */
    public void open()
    {
        int absX = getAbsoluteX();
        int absY = getAbsoluteY();

        popupMenu.setSize(popupMenu.getPreferredSize());

        if ((popupOrientation & ABOVE_PLACEMENT) > 0)
            absY -= popupMenu.height;
        else if ((popupOrientation & BELOW_PLACEMENT) > 0)
            absY += height;
        else if ((popupOrientation & LEFT_PLACEMENT) > 0)
            absX -= popupMenu.width;
        else if ((popupOrientation & RIGHT_PLACEMENT) > 0)
            absX += width;

        popupMenu.setLocation(absX, absY);
        popupMenu.setVisible(true);

        setState(PRESSED);
        repaint();

        isOpened = true;
    }

    /**
     * Closes popup menu associated with this menu
     */
    public void close()
    {
        popupMenu.setVisible(false);
        isOpened = false;

        requestFocus();
    }

    /**
     * Returns weather popup menu is opened or closed.
     * @return true/false
     */
    public boolean isOpened()
    {
        return isOpened;
    }

    /**
     * Asjusts popup menu placement setting.
     * Depending on placement popup menu can appear
     * either to the left of menu, right, above or bottom.
     * @param popupPlacement Popup menu placement flag
     */
    public void setPopupPlacement(int popupPlacement)
    {
        this.popupOrientation = popupPlacement;
        popupMenu.setPopupOrientation(popupPlacement);
    }

    /**
     * Sets arrow image for this menu
     * @param image Arrow image
     */
    public void setArrowImage(CustomImage image)
    {
        this.arrowImage = image;
        invalidate();
    }

    /**
     * Returns arrow image.
     * @return Arrow image, null if none set.
     */
    public CustomImage getArrowImage()
    {
        return arrowImage;
    }

    public void setState(int index)
    {
        if (isOpened())
            index = PRESSED;
         
        super.setState(index);

        //System.out.println(toString()+" state="+index);
        
        CustomImage image = (CustomImage) currentStyle.attributes.get("arrow-image");
        if (image == null)
        {
            image = new CustomImage(createArrowImage());
            currentStyle.addAttribute("arrow-image", image);
            setArrowImage(image);
        }
        else
            setArrowImage(image.clone());        
    }

    /**
     * Creates arrow image if custom one was not set
     * @return Image
     */
    protected static Image createArrowImage()
    {
        int[] data = { 0xFF000000, 0x00FFFFFF, 0x00FFFFFF,
                       0x00FFFFFF, 0xFF000000, 0x00FFFFFF,
                       0xFF000000, 0x00FFFFFF, 0x00FFFFFF };

        return Image.createRGBImage(data, 3, 3, true);
    }

    protected void paintComponent(Graphics g)
    {
        int prevTranslateX = g.getTranslateX();
        int prevTranslateY = g.getTranslateY();

        super.paintComponent(g);

        if (arrowImage != null && parentMenu != null)
        {
            g.translate(prevTranslateX - g.getTranslateX(), prevTranslateY - g.getTranslateY());
            arrowImage.paint(g, clientSize.width-1, clientSize.height >> 1, Graphics.RIGHT | Graphics.VCENTER);
        }
    }

    /*protected void processFocusEvent(FocusEvent event)
    {
        super.processFocusEvent(event);

        if (this.isFocused && parentMenu == null && !isOpened)
            open();
    } */
}
